package edu.ccut.saturn.studio.wfg.editor;

import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.w3c.dom.Document;

import edu.ccut.saturn.studio.wfg.model.Shape;
import edu.ccut.saturn.studio.wfg.model.ShapesDiagram;
import edu.ccut.saturn.studio.wfg.utils.ModelXmlUtils;
import edu.ccut.saturn.studio.wfg.xml.loader.NodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnAutoActivityNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnEndNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnHumanNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnInfoNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnRouterLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnStartNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnSubActivityNodeLoader;

public class WfgMultiPageEditor extends MultiPageEditorPart implements
		IResourceChangeListener, ITabbedPropertySheetPageContributor {

	private WfgEditors wfgEditor;

	private StructuredTextEditor textEditor;

	private int wfgEditorIndex = 0;

	private int textEditorIndex = 0;

	private Document document;

	private Document getDocument(StructuredTextEditor textEditor) {
		Document document = (Document) textEditor.getAdapter(Document.class);
		if (document.getDocumentElement() == null) {
			String workspace = ResourcesPlugin.getWorkspace().getRoot()
					.getLocation().toOSString();
			String path = ((FileEditorInput) getEditorInput()).getPath()
					.toOSString();
			String projectName = path.replace(workspace, "").split("\\\\")[1];
			this.refreshProject(projectName);
		}
		return document;
	}

	public StructuredTextEditor getTextEditor() {
		return textEditor;
	}

	public WfgEditors getShapesEditor() {
		return wfgEditor;
	}

	@SuppressWarnings("deprecation")
	private void createGraphicalEditPage() {
		List<Shape> shapes = ModelXmlUtils.loadModels(document,
				new NodeLoader[] { new SaturnInfoNodeLoader(),
						new SaturnStartNodeLoader(), new SaturnEndNodeLoader(),
						new SaturnHumanNodeLoader(), new SaturnRouterLoader(),
						new SaturnAutoActivityNodeLoader(),
						new SaturnSubActivityNodeLoader() });
		if (wfgEditor == null) {
			this.wfgEditor = new WfgEditors(shapes);
		}
		try {
			this.wfgEditorIndex = addPage(this.wfgEditor, getEditorInput());

			setPageText(this.wfgEditorIndex, "flow");
			setTitle(getEditorInput().getName());
		} catch (PartInitException e) {
			e.printStackTrace();
		}
	}

	private void createSourcePage() {
		try {
			textEditor = new StructuredTextEditor();
			this.textEditorIndex = addPage(textEditor, getEditorInput());
			setPageText(this.textEditorIndex, "source");
			this.document = getDocument(textEditor);
		} catch (PartInitException e) {
			e.printStackTrace();
		}
	}

	protected void createPages() {
		createSourcePage();
		createGraphicalEditPage();
		this.setActivePage(this.wfgEditorIndex);

	}

	public void doSave(IProgressMonitor monitor) {
		ModelXmlUtils.refreshModelXml(document, wfgEditor.getDiagram()
				.getShapes());
		this.wfgEditor.doSave(monitor);
		textEditor.doSave(monitor);
	}

	public void doSaveAs() {

	}

	public boolean isSaveAsAllowed() {
		return false;
	}

	public void resourceChanged(IResourceChangeEvent event) {

	}

	@Override
	protected void pageChange(int newPageIndex) {
		if (newPageIndex == this.textEditorIndex) {
			ModelXmlUtils.refreshModelXml(document, wfgEditor.getDiagram()
					.getShapes());
		}

		super.pageChange(newPageIndex);
	}

	private void refreshProject(String projectName) {
		IResource bufferRes = findMember(ResourcesPlugin.getWorkspace()
				.getRoot(), projectName);
		if (bufferRes != null && bufferRes.isAccessible()) {
			try {
				bufferRes.refreshLocal(IResource.DEPTH_INFINITE, null);
			} catch (CoreException e) {
				e.printStackTrace();
			}
		}
	}

	private IResource findMember(IWorkspaceRoot root, String path) {
		Path pathOrNull = pathOrNull(path);
		if (pathOrNull == null)
			return null;
		return root.findMember(pathOrNull);
	}

	public ShapesDiagram getDiagram() {
		return this.wfgEditor.getDiagram();
	}

	public String getContributorId() {
		return getSite().getId();
	}

	@SuppressWarnings("unchecked")
	public Object getAdapter(Class adapter) {
		if (adapter == IPropertySheetPage.class) {
			return new TabbedPropertySheetPage(this);
		}
		return super.getAdapter(adapter);
	}

	private Path pathOrNull(String p) {
		if (p == null || p.trim().length() == 0) {
			return null;
		} else {
			return new Path(p);
		}
	}
}
